﻿#include "ctpinterface.h"

CTPInterface::CTPInterface(QObject *parent) :
    QObject(parent)
{
    ServerName = "";
    ServerTradeAddr = "";
    ServerMarketAddr = "";

}

bool CTPInterface::InitTradeObject(QString strUserName,QString strPassword,QString strBrokerID,QString strServerName){

    QDir dir;
    QString currentPath=dir.currentPath();
    QString sParentDir = currentPath;
    QString sTradeDir;

    //创建TradeCon文件的目录
    sParentDir.append("/").append(strUserName);
    sTradeDir = sParentDir;
    sTradeDir.append("/TradeCon");

    if (!dir.exists(sParentDir)){
        if (!dir.mkdir(sParentDir)){
            QMessageBox::critical(NULL, QString("ERROR"), QString("创建账户目录失败"));
            return false;
        }
    }

    if (!dir.exists(sTradeDir)){
        if (!dir.mkdir(sTradeDir)){
            QMessageBox::critical(NULL, QString("ERROR"), QString("Fail To Create TradeConDir"));
            return false;
        }
    }
    sTradeDir = sTradeDir + "/";

    //初始化交易服务器
    m_pTradeUserApi = CThostFtdcTraderApi::CreateFtdcTraderApi(sTradeDir.toStdString().c_str());
    m_pThostFtdcTraderSpiImpl = new CThostFtdcTraderSpiImpl();
    m_pThostFtdcTraderSpiImpl->SetUserApi(m_pTradeUserApi);
    m_pThostFtdcTraderSpiImpl->SetUserAndPassword(strBrokerID,strUserName,strPassword);
    m_pThostFtdcTraderSpiImpl->SetMainDlg(this);
    m_pTradeUserApi->RegisterSpi((CThostFtdcTraderSpi*)m_pThostFtdcTraderSpiImpl);

    m_pTradeUserApi->SubscribePublicTopic(THOST_TERT_RESTART);
    m_pTradeUserApi->SubscribePrivateTopic(THOST_TERT_QUICK);

	QString qstrTradeFront = "tcp://" + ServerTradeAddr;
    char*  pszTradeFront;
    QByteArray bTrade = qstrTradeFront.toLatin1();
    pszTradeFront=bTrade.data();

    //注册交易前置
    m_pTradeUserApi->RegisterFront(pszTradeFront);
    m_pTradeUserApi->Init();
    return true;
}

bool CTPInterface::InitMdObject(QString strUserName,QString strPassword,QString strBrokerID){

    QDir dir;
    QString currentPath=dir.currentPath();
    QString sParentDir = currentPath;
    QString sMdDir;

    //创建MdCon文件的目录
    sParentDir.append("/").append(strUserName);
    sMdDir = sParentDir;
    sMdDir.append("/MdCon");

    if (!dir.exists(sParentDir))
    {
        if (!dir.mkdir(sParentDir))
        {
            QMessageBox::critical(NULL, QString("ERROR"), QString("创建账户目录失败"));
            return false;
        }
    }

    if (!dir.exists(sMdDir))
    {
        if (!dir.mkdir(sMdDir))
        {
            QMessageBox::critical(NULL, QString("ERROR"), QString("Fail To Create MdConDir"));
            return false;
        }
    }
    sMdDir = sMdDir + "/";

    //初始化行情服务器
    m_pmdUserApi = CThostFtdcMdApi::CreateFtdcMdApi(sMdDir.toStdString().c_str());
    m_pThostFtdcMdSpiImpl = new CThostFtdcMdSpiImpl();
    m_pThostFtdcMdSpiImpl->SetUserApi(m_pmdUserApi);
    m_pThostFtdcMdSpiImpl->SetUserAndPassword(strBrokerID,strUserName,strPassword);
    m_pThostFtdcMdSpiImpl->SetMainDlg(this);
    m_pmdUserApi->RegisterSpi((CThostFtdcMdSpi *)m_pThostFtdcMdSpiImpl);

	QString qstrMDFront = "tcp://" + ServerMarketAddr;
    char* pszMdFront;
    QByteArray bMd = qstrMDFront.toLatin1();
    pszMdFront=bMd.data();
    //注册行情前置
    m_pmdUserApi->RegisterFront(pszMdFront);
    m_pmdUserApi->Init();

    return true;
}
///查询资金账户
void CTPInterface::ReqQryTradingAccount(){
    CThostFtdcQryTradingAccountField oQryTradingAccount;
    memset(&oQryTradingAccount,0,sizeof(CThostFtdcQryTradingAccountField));
    strcpy(oQryTradingAccount.BrokerID   , m_pThostFtdcTraderSpiImpl->m_logininfo.BrokerID);///经纪公司代码
    strcpy(oQryTradingAccount.InvestorID , m_pThostFtdcTraderSpiImpl->m_logininfo.UserID);///投资者代码
    strcpy(oQryTradingAccount.CurrencyID , "CNY");///币种代码

    if(m_pTradeUserApi != NULL){
        m_pTradeUserApi->ReqQryTradingAccount(&oQryTradingAccount,m_pThostFtdcTraderSpiImpl->GetRequestId());
    }
}

bool CTPInterface::ReqQrySettlementInfoConfirm(){
    //请求查询结算信息确认
    CThostFtdcQrySettlementInfoConfirmField oQrySettlementInfoConfirm;
    strncpy_s(oQrySettlementInfoConfirm.BrokerID,this->m_pThostFtdcTraderSpiImpl->m_logininfo.BrokerID,sizeof(oQrySettlementInfoConfirm.BrokerID));///经纪公司代码
    strncpy_s(oQrySettlementInfoConfirm.InvestorID,this->m_pThostFtdcTraderSpiImpl->m_logininfo.UserID,sizeof(oQrySettlementInfoConfirm.InvestorID));///投资者代码

    if(m_pTradeUserApi != NULL){
        this->m_pTradeUserApi->ReqQrySettlementInfoConfirm(&oQrySettlementInfoConfirm,this->m_pThostFtdcTraderSpiImpl->GetRequestId());
    }

    return true;
}

bool CTPInterface::ReqQryInstrument(){

    ///请求查询所有合约
    CThostFtdcQryInstrumentField req;
    memset(&req, 0, sizeof(req));
    strcpy_s(req.InstrumentID, "");//为空表示查询所有合约

    if(m_pTradeUserApi != NULL){
        m_pTradeUserApi->ReqQryInstrument(&req,m_pThostFtdcTraderSpiImpl->GetRequestId());
    }

    return true;
}
//委托
void CTPInterface::OrderInsert(const char* exch_type, const char* contract_code,
                               char c_bs, char c_direction, char c_hedge,
                               int l_entrust_amount, double en_entrust_price,QString entrust_prop){
    CThostFtdcInputOrderField OrderInfo;
    memset(&OrderInfo, 0, sizeof(CThostFtdcInputOrderField));

    ///合约代码
    strncpy(OrderInfo.InstrumentID, contract_code, sizeof(TThostFtdcInstrumentIDType));
    ///买卖方向
    OrderInfo.Direction = c_bs;

    if(entrust_prop == "F0"){
        OrderInfo.OrderPriceType = THOST_FTDC_OPT_LimitPrice;///报单价格条件类型：限价
        OrderInfo.LimitPrice = en_entrust_price;///价格
        OrderInfo.TimeCondition =   THOST_FTDC_TC_GFD;///有效期类型：当日有效
    }else if(entrust_prop == "F1"){/*市价*/
        OrderInfo.OrderPriceType = THOST_FTDC_OPT_AnyPrice;///报单价格条件类型：任意价
        OrderInfo.LimitPrice = 0;///价格
        OrderInfo.TimeCondition =   THOST_FTDC_TC_IOC;///有效期类型：立即完成，否则撤销
    }

    if(c_direction == '1'){//开仓
        OrderInfo.CombOffsetFlag[0]='0';
    }else if(c_direction == '2'){//平仓
        OrderInfo.CombOffsetFlag[0]='1';
    }else if(c_direction == '4'){//平今仓
        OrderInfo.CombOffsetFlag[0]='3';
    }
    ///组合投机套保标志 //0投机；1套保
    //OrderInfo.CombHedgeFlag[0]=GetHedgeFlag(myOrder->Hedge);
    OrderInfo.CombHedgeFlag[0]= '1';

    ///数量
    OrderInfo.VolumeTotalOriginal = l_entrust_amount;
    ///成交量类型 任意数量
    OrderInfo.VolumeCondition = THOST_FTDC_VC_AV;
    ///触发条件:立即
    OrderInfo.ContingentCondition = THOST_FTDC_CC_Immediately;

    ///最小成交量 1
    OrderInfo.MinVolume = 1;
    ///强平原因 非强平
    OrderInfo.ForceCloseReason = THOST_FTDC_FCC_NotForceClose;
    ///自动挂起标志 否
    OrderInfo.IsAutoSuspend = 0;
    ///用户强平标志 否
    OrderInfo.UserForceClose = 0;

    //报单引用
    TThostFtdcOrderRefType NewOrderRef;
    int iOrderRef;
    strncpy_s(NewOrderRef,sizeof(TThostFtdcOrderRefType),m_pThostFtdcTraderSpiImpl->m_logininfo.MaxOrderRef,sizeof(TThostFtdcOrderRefType));
    iOrderRef=atoi(NewOrderRef);
    iOrderRef++;
    itoa(iOrderRef,NewOrderRef,10);
    strncpy_s(m_pThostFtdcTraderSpiImpl->m_logininfo.MaxOrderRef,sizeof(TThostFtdcOrderRefType),NewOrderRef,sizeof(TThostFtdcOrderRefType));

    strncpy_s(OrderInfo.BrokerID,sizeof(TThostFtdcBrokerIDType),m_pThostFtdcTraderSpiImpl->m_logininfo.BrokerID,sizeof(TThostFtdcBrokerIDType));
    strncpy_s(OrderInfo.InvestorID,sizeof(TThostFtdcInvestorIDType),m_pThostFtdcTraderSpiImpl->m_logininfo.UserID,sizeof(TThostFtdcInvestorIDType));
    strncpy_s(OrderInfo.OrderRef,sizeof(TThostFtdcOrderRefType),m_pThostFtdcTraderSpiImpl->m_logininfo.MaxOrderRef,sizeof(TThostFtdcOrderRefType));
    strncpy_s(OrderInfo.UserID,sizeof(TThostFtdcUserIDType),m_pThostFtdcTraderSpiImpl->m_logininfo.UserID,sizeof(TThostFtdcUserIDType));

    if(m_pTradeUserApi != NULL){
        m_pTradeUserApi->ReqOrderInsert(&OrderInfo,this->m_pThostFtdcTraderSpiImpl->GetRequestId());
    }
}
///请求查询投资者持仓
void CTPInterface::ReqQryInvestorPosition(){

    CThostFtdcQryInvestorPositionField posinfo;
    memset(&posinfo,0,sizeof(CThostFtdcQryInvestorPositionField));
    strncpy_s(posinfo.BrokerID,m_pThostFtdcTraderSpiImpl->m_logininfo.BrokerID,sizeof(TThostFtdcBrokerIDType));///经纪公司代码
    strncpy_s(posinfo.InvestorID,m_pThostFtdcTraderSpiImpl->m_logininfo.UserID,sizeof(TThostFtdcInvestorIDType));///投资者代码

    if(m_pTradeUserApi != NULL){
        m_pTradeUserApi->ReqQryInvestorPosition(&posinfo,this->m_pThostFtdcTraderSpiImpl->GetRequestId());
    }
}

///订阅行情
void CTPInterface::SubscribeMarketData(QStringList lst){

	int iSubscribeCnt = 0;
	int iCnt = lst.size();
	QStringList tmplst;
	if(iCnt > 0 ){
		for(int i = 0; i < iCnt; i++){
			QString str = lst.at(i);
			if(!m_SubscribeCodesLst.contains(str)){
				m_SubscribeCodesLst<<str;
				iSubscribeCnt ++;
				tmplst << str;
			}
		}
	}

    iCnt = tmplst.size();
    if(iCnt > 0 ){
        char** ppInstrument=new char*[iCnt];
        for(int i =0; i < iCnt; i++){
			QString str = lst.at(i);
			char* Instrtmp = new char [sizeof(TThostFtdcInstrumentIDType)];
			strncpy_s(Instrtmp,sizeof(TThostFtdcInstrumentIDType),str.toStdString().c_str(),sizeof(TThostFtdcInstrumentIDType));
			ppInstrument[i]=Instrtmp;
        }
        if(m_pmdUserApi != NULL && iSubscribeCnt > 0){
            m_pmdUserApi->SubscribeMarketData(ppInstrument,iSubscribeCnt);
        }
    }
}
///请求查询成交
void CTPInterface::ReqQryTrade(){
    CThostFtdcQryTradeField tradoinfo;
    memset(&tradoinfo,0,sizeof(CThostFtdcQryTradeField));

    strncpy_s(tradoinfo.BrokerID,m_pThostFtdcTraderSpiImpl->m_logininfo.BrokerID,sizeof(TThostFtdcBrokerIDType));
    strncpy_s(tradoinfo.InvestorID,m_pThostFtdcTraderSpiImpl->m_logininfo.UserID,sizeof(TThostFtdcInvestorIDType));

    if(m_pTradeUserApi != NULL){
        m_pTradeUserApi->ReqQryTrade(&tradoinfo,this->m_pThostFtdcTraderSpiImpl->GetRequestId());
    }
}
///撤销委托
void CTPInterface::DeleteOrder(TThostFtdcOrderSysIDType& entrust_no,TThostFtdcExchangeIDType& ExchangeID){

    CThostFtdcInputOrderActionField req;
    memset(&req, 0, sizeof(req));
    strncpy_s(req.BrokerID,sizeof(TThostFtdcBrokerIDType),m_pThostFtdcTraderSpiImpl->m_logininfo.BrokerID,sizeof(TThostFtdcBrokerIDType));
    strncpy_s(req.InvestorID,sizeof(TThostFtdcInvestorIDType),m_pThostFtdcTraderSpiImpl->m_logininfo.UserID,sizeof(TThostFtdcInvestorIDType));
    strncpy_s(req.ExchangeID,sizeof(TThostFtdcExchangeIDType),ExchangeID,sizeof(TThostFtdcExchangeIDType));
    strncpy_s(req.OrderSysID, sizeof(TThostFtdcOrderSysIDType),entrust_no,sizeof(TThostFtdcOrderSysIDType));
    req.ActionFlag = THOST_FTDC_AF_Delete;  //操作标志

    if(m_pTradeUserApi != NULL){
        m_pTradeUserApi->ReqOrderAction(&req,this->m_pThostFtdcTraderSpiImpl->GetRequestId());
    }
}

void CTPInterface::ReqSettlementInfoConfirm(){

    //投资者结算结果确认
    CThostFtdcSettlementInfoConfirmField qrySettlementInfo;
    QString Time = QTime::currentTime().toString("hh:mm:ss");

    strncpy_s(qrySettlementInfo.BrokerID,m_pThostFtdcTraderSpiImpl->m_logininfo.BrokerID,sizeof(qrySettlementInfo.BrokerID));
    strncpy_s(qrySettlementInfo.InvestorID,m_pThostFtdcTraderSpiImpl->m_logininfo.UserID,sizeof(qrySettlementInfo.InvestorID));
    strncpy_s(qrySettlementInfo.ConfirmDate,m_pThostFtdcTraderSpiImpl->m_logininfo.TradingDay,sizeof(qrySettlementInfo.InvestorID));
    strncpy_s(qrySettlementInfo.ConfirmTime,Time.toStdString().c_str(),sizeof(qrySettlementInfo.InvestorID));

    if(m_pTradeUserApi != NULL){
        m_pTradeUserApi->ReqSettlementInfoConfirm(&qrySettlementInfo,m_pThostFtdcTraderSpiImpl->GetRequestId());
    }
}
///请求查询合约保证金率
void CTPInterface::ReqQryInstrumentMarginRate(QString InstrumentID,TThostFtdcHedgeFlagType  HedgeFlag){
    CThostFtdcQryInstrumentMarginRateField pRate;

    strncpy_s(pRate.BrokerID,m_pThostFtdcTraderSpiImpl->m_logininfo.BrokerID,sizeof(pRate.BrokerID));
    strncpy_s(pRate.InvestorID,m_pThostFtdcTraderSpiImpl->m_logininfo.UserID,sizeof(pRate.InvestorID));
    strncpy_s(pRate.InstrumentID,InstrumentID.toStdString().c_str(),sizeof(pRate.InstrumentID));
    pRate.HedgeFlag = HedgeFlag;

    if(m_pTradeUserApi != NULL){
        m_pTradeUserApi->ReqQryInstrumentMarginRate(&pRate,m_pThostFtdcTraderSpiImpl->GetRequestId());
    }
}
